#include "textura.h"
#include "texcomprimida.h"
#include "iobmp.h"
#include <GL/glut.h>
#include <iostream>
using namespace std;

class Skybox{
private:
    Textura* tex_daylight;
    Textura* tex_night;
    IObmp* io;
    float distancia;
    GLuint dl_handle_daylight;
    GLuint dl_handle_night;
    bool daylight;
public:
    Skybox(float distancia):distancia(4*distancia), daylight(true){
        io = new IObmp();
        daylight = true;
        Texels& texelsDay = io->cargarBMP("../res/dia.bmp");
        tex_daylight = new TexturaComprimida(texelsDay);
        Texels& texelsNight = io->cargarBMP("../res/night.bmp");
        tex_night = new TexturaComprimida(texelsNight);

        tex_daylight->setUso(GL_MODULATE);
        tex_night->setUso(GL_MODULATE);

       tex_daylight->setWrapS(GL_CLAMP_TO_EDGE);
       tex_daylight->setWrapT(GL_CLAMP_TO_EDGE);

       tex_night->setWrapS(GL_CLAMP_TO_EDGE);
       tex_night->setWrapT(GL_CLAMP_TO_EDGE);

       tex_daylight->setMinificador(GL_LINEAR);
       tex_daylight->setMagnificador(GL_LINEAR);
       
       tex_night->setMinificador(GL_LINEAR);
       tex_night->setMagnificador(GL_LINEAR);

        delete &texelsDay;
        delete &texelsNight;

        dl_handle_daylight = glGenLists(1);
        dl_handle_night = glGenLists(1);
        glNewList(dl_handle_daylight, GL_COMPILE);
		    initDaylight();
	    glEndList();
	    glNewList(dl_handle_night, GL_COMPILE);
	        initNight();
	    glEndList();

         cambiarLuces();
    }

    void switchTime(){
       daylight = not daylight;
       cambiarLuces();
    }

    void cambiarLuces() {
       if (daylight){
          glEnable(GL_LIGHT0);
          glDisable(GL_LIGHT1);
          /*
          glDisable(GL_LIGHT2);
          glDisable(GL_LIGHT3);
          glDisable(GL_LIGHT4);
          */
       }
       else{
          glEnable(GL_LIGHT1);
          
          /*
          glEnable(GL_LIGHT2);
          glEnable(GL_LIGHT3);
          glEnable(GL_LIGHT4);
          */
          glDisable(GL_LIGHT0);
       }
    }

    virtual ~Skybox(){
        delete io;
        delete tex_daylight;
        delete tex_night;
    }

    void dibujar(){
    	if(daylight){
    		glCallList(dl_handle_daylight);
    	}
    	else {
    		glCallList(dl_handle_night);
    	}
    }

    void setPosicionLuces() {
    	static float light_position[4] = {10.0f, 10.0f, 8.0f, 0.0};
    	glLightfv(GL_LIGHT0, GL_POSITION, light_position);
        
        static float light_position1[4] = {-10, -10, 6.0f, 1.0};
        static float spot_dir1[3] = {5.0f, 5.0f, -1.0f};
        glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
        glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_dir1);
        
        /*
        static float light_position2[4] = {distancia/4 + 10, distancia/4 + 10, 5.0f, 1.0};
        static float spot_dir2[3] = {-5.0f, -5.0f, -1.0f};
        glLightfv(GL_LIGHT2, GL_POSITION, light_position2);
        glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, spot_dir2);
        
        
        static float light_position3[4] = {-10, distancia/4 + 10, 5.0f, 1.0};
        static float spot_dir3[3] = {5.0f, -5.0f, -1.0f};
        glLightfv(GL_LIGHT3, GL_POSITION, light_position3);
        glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, spot_dir3);
        
        static float light_position4[4] = {distancia/4 + 10, -10, 5.0f, 1.0};
        static float spot_dir4[3] = {-5.0f, 5.0f, -1.0f};
        glLightfv(GL_LIGHT4, GL_POSITION, light_position4);
        glLightfv(GL_LIGHT4, GL_SPOT_DIRECTION, spot_dir4);
        */
    }

    void setDaylightIllum(){
        static GLfloat lmodel_ambient[] = { 0.05, 0.05, 0.05, 1.0 };
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
        //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
        glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
        
    	// Luz del sol
    	static float light_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
    	static float light_ambient[4] = {0.99f, 0.99f, 0.99f, 1.0f};

    	glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color);
    	glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
    	
        
        // Luz de la luna
        float luz_luna_specular[4] = {1, 1, 1, 1.0f};
        float luz_luna[4] = {0.5f, 0.5f, 0.5, 1.0f};
        float light_ambient1[4] = {0.2f, 0.2f, 0.7f, 1.0f};
        float spot_cutoff1[1] = {35.0f};

        glLightfv(GL_LIGHT1, GL_DIFFUSE, luz_luna);
        glLightfv(GL_LIGHT1, GL_SPECULAR, luz_luna_specular);
        glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient1);
        glLightfv(GL_LIGHT1, GL_SPOT_CUTOFF, spot_cutoff1);
        
        /*
        glLightfv(GL_LIGHT2, GL_DIFFUSE, light_color1);
        glLightfv(GL_LIGHT2, GL_AMBIENT, light_ambient1);
        glLightfv(GL_LIGHT2, GL_SPOT_CUTOFF, spot_cutoff1);
        
        
        glLightfv(GL_LIGHT3, GL_DIFFUSE, light_color1);
        glLightfv(GL_LIGHT3, GL_AMBIENT, light_ambient1);
        glLightfv(GL_LIGHT3, GL_SPOT_CUTOFF, spot_cutoff1);
        
        glLightfv(GL_LIGHT4, GL_DIFFUSE, light_color1);
        glLightfv(GL_LIGHT4, GL_AMBIENT, light_ambient1);
        glLightfv(GL_LIGHT4, GL_SPOT_CUTOFF, spot_cutoff1);
       
        */
       /* 
        glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 0.0);
        glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.01);
        glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0);
        glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 1.0);
      */
    }

    void dibujarSkybox() {

       glPushAttrib(GL_ALL_ATTRIB_BITS);
       glDisable(GL_LIGHTING);

       glMatrixMode(GL_TEXTURE);
       glPushMatrix();
       glLoadIdentity();

       glMatrixMode(GL_MODELVIEW);
       glPushMatrix();


       glScalef(distancia,distancia,distancia);
       glTranslatef(-.25, -.25, -0.5);

       glBegin(GL_QUADS);

       //cerca
       glTexCoord2f(0, 1);
       glVertex3f(1.0,1.0,0.0);
       glTexCoord2f(.25, 1);
       glVertex3f(1.0,0.0,0.0);
       glTexCoord2f(.25, .5);
       glVertex3f(1.0,0.0,1.0);
       glTexCoord2f(0, 0.5);
       glVertex3f(1.0,1.0,1.0);

       //izquierda
       glTexCoord2f(.25, .5);
       glVertex3f(1.0,0.0,1.0);
       glTexCoord2f(.25, 1);
       glVertex3f(1.0,0.0,0.0);
       glTexCoord2f(.5, 1);
       glVertex3f(0.0,0.0,0.0);
       glTexCoord2f(.5, .5);
       glVertex3f(0.0,0.0,1.0);

       //lejos
       glTexCoord2f(.75, .5);
       glVertex3f(0.0,1.0,1.0);
       glTexCoord2f(.5, .5);
       glVertex3f(0.0,0.0,1.0);
       glTexCoord2f(.5, 1);
       glVertex3f(0.0,0.0,0.0);
       glTexCoord2f(.75, 1);
       glVertex3f(0.0,1.0,0.0);

       //derecha
       glTexCoord2f(.75, .5);
       glVertex3f(0.0,1.0,1.0);
       glTexCoord2f(.75, 1);
       glVertex3f(0.0,1.0,0.0);
       glTexCoord2f(1, 1);
       glVertex3f(1.0,1.0,0.0);
       glTexCoord2f(1, .5);
       glVertex3f(1.0,1.0,1.0);


       //arriba
       glTexCoord2f(.25, .5);
       glVertex3f(1.0,0.0,1.0);  // (1,0,1)
       glTexCoord2f(.5, .5);
       glVertex3f(0.0,0.0,1.0); // (0,0,1)
       glTexCoord2f(.5, 0);
       glVertex3f(0.0,1.0,1.0); // (0,1,1)
       glTexCoord2f(.25, 0);
       glVertex3f(1.0,1.0,1.0); // (1,1,1)

     glEnd();
       
       glMatrixMode(GL_TEXTURE);
       glPopMatrix();
       glMatrixMode(GL_MODELVIEW);
       glPopMatrix();

       glPopAttrib();
    }

    void initDaylight(){
       tex_daylight->enlazar();
       dibujarSkybox();
       tex_daylight->desenlazar();
    }

    void initNight(){
       tex_night->enlazar();
       dibujarSkybox();
       tex_night->desenlazar();
    }
};
